package A3GCConcreteTestCase;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.jgroups.Address;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.View;

import A3JGroups.A3JGMessage;
import A3JGroups.JGSupervisorRole;

public class LocationSupervisorRole extends JGSupervisorRole 
{
	ConcurrentLinkedQueue<A3JGMessage> myProcessQueue; // probably need this to a distributed
	HashMap<String, Address> myClients;
	
	public LocationSupervisorRole(int resourceCost, String groupName) 
	{
		super(resourceCost, groupName);
		
		myProcessQueue = new ConcurrentLinkedQueue<A3JGMessage>();
		
	}

	@Override
	public void run() 
	{
		while ( this.active )
		{
			if ( !(myProcessQueue.isEmpty()) )
			{
				A3JGMessage mex = myProcessQueue.poll();
				
				// figure out the group
				String msg = mex.getContent().toString();
				String gn  = msg.substring(0, msg.indexOf('#') );
				
				//modify the content
				String content = mex.getContent().toString();
				content = content + "#" + getGroupName();
				mex.setContent(content);
				
				// send to the supervisor
				Address addr = node.getSupervisorMap().get(gn);
				Message m = new Message();
				//mex.getContent().toString() + "#" + 
				m.setObject(mex);
				m.setDest(addr);
				JChannel chan = node.getChannels(gn);
				System.out.println("LocationSupervisor[" + this.getNode().getID() + "," + getChan().getAddress().toString() + "] is trying to send a message <" + msg + "> to addr <" + addr + "> of group <" + gn + ">" );
				
				try 
				{
					chan.send( m );
				}
				catch (Exception e) 
				{
					e.printStackTrace();
				}

			}
			else
			{
				try 
				{
					Thread.sleep(500); // go to sleep for a bit.
				} 
				catch (InterruptedException e) 
				{
					e.printStackTrace();
				} 
			}
		}
	}

	@Override
	public void messageFromFollower(A3JGMessage msg) 
	{
		// place to queue
		System.out.println("LocationSupervisor[" + this.getNode().getID() + "," + getChan().getAddress().toString() + "]::messageFromFollower: Recevied a msg <" + msg.getContent().toString() + ">" );
		myProcessQueue.add( msg );
	}

	@Override
	public void updateFromFollower(A3JGMessage msg) 
	{
		// would need to pass the message back to the client
		System.out.println("LocationSupervisor[" + this.getNode().getID() + "," + getChan().getAddress().toString() + "]::updateFromFollower: Recevied a msg <" + msg.getContent().toString() + ">");
		String splits[] = msg.getContent().toString().split("#");
		String straddr;
		Address retaddr;
		
		straddr = splits[2];
		
		View curview = getChan().getView();
		
		Iterator<Address> iter = curview.iterator();
		
		retaddr = null;
		while ( iter.hasNext() )
		{
			Address addr = iter.next();
			
			if ( addr.toString().compareTo(straddr) == 0 )
			{
				// match found 
				retaddr = addr;
				break;
			}
		}
		
		if ( retaddr == null ) // lost client
			return;
		
		List<Address> list = new ArrayList<Address>();
		list.add(retaddr);
		sendMessageToFollower(msg, list);
	}

	@Override
	public int fitnessFunc() 
	{
		return 0;
	}

}
